//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "rtc_bsp.h"
#include "../EXTI_BSP/exti_bsp.h"


static WHT_RTC_IT_CB_t WHT_RTC_IT_CB;

/*RTC 2个闹钟事件回调函数*/
static void RTC_BSP_Alarm_IT_CB(void)
{
	if (RTC_GetITStatus(RTC_IT_ALRA) == SET)
	{
		if (WHT_RTC_IT_CB.Alarm_A_Interrupt_Callback)
			WHT_RTC_IT_CB.Alarm_A_Interrupt_Callback();
		RTC_ClearITPendingBit(RTC_IT_ALRA);//clear RTC Alarm IT
	}
	else if (RTC_GetITStatus(RTC_IT_ALRB) == SET)
	{
		if (WHT_RTC_IT_CB.Alarm_B_Interrupt_Callback)
			WHT_RTC_IT_CB.Alarm_B_Interrupt_Callback();
		RTC_ClearITPendingBit(RTC_IT_ALRB);//clear RTC Alarm IT
	}
}
/*RTC 篡改和入侵回调函数*/
static void RTC_BSP_TAMP_STAMP_IT_CB(void)
{
	if (RTC_GetITStatus(RTC_IT_TS) == SET)
	{
		if (WHT_RTC_IT_CB.Time_Stamp_Interrupt_Callback)
			WHT_RTC_IT_CB.Time_Stamp_Interrupt_Callback();
		RTC_ClearITPendingBit(RTC_IT_TS);
	}
	else if (RTC_GetITStatus(RTC_IT_TAMP1) == SET)
	{
		if (WHT_RTC_IT_CB.Tamper_Interrupt_Callback)
			WHT_RTC_IT_CB.Tamper_Interrupt_Callback();
		RTC_ClearITPendingBit(RTC_IT_TAMP1);
	}
	else if (RTC_GetITStatus(RTC_IT_TAMP2) == SET)
	{
		if (WHT_RTC_IT_CB.Tamper_Interrupt_Callback)
			WHT_RTC_IT_CB.Tamper_Interrupt_Callback();
		RTC_ClearITPendingBit(RTC_IT_TAMP2);
	}
}
/*RTC 唤醒回调函数*/
static void RTC_BSP_Wakeup_IT_CB(void)
{
	if (RTC_GetITStatus(RTC_IT_WUT) == SET)
	{
		if (WHT_RTC_IT_CB.Wakeup_Interrupt_Callback)
			WHT_RTC_IT_CB.Wakeup_Interrupt_Callback();
		RTC_ClearITPendingBit(RTC_IT_WUT);
	}
}


/*RTC注册中断回调函数*/
static void WHT_RTC_BSP_Register_IT_CB(const WHT_RTC_IT_CB_t* it_cb)
{
	WHT_EXTI_Config_t WHT_EXTI_Config =
	{
		.Type = Exti_Event,
		.Trigger = Trigger_Rising,//RTC所有事件均是上升沿触发
		.Mode = Mode_Interrupt,
	};
	
	WHT_RTC_IT_CB.Alarm_A_Interrupt_Callback = it_cb->Alarm_A_Interrupt_Callback;
	WHT_RTC_IT_CB.Alarm_B_Interrupt_Callback = it_cb->Alarm_B_Interrupt_Callback;
	WHT_RTC_IT_CB.Wakeup_Interrupt_Callback = it_cb->Wakeup_Interrupt_Callback;
	WHT_RTC_IT_CB.Time_Stamp_Interrupt_Callback = it_cb->Time_Stamp_Interrupt_Callback;
	WHT_RTC_IT_CB.Tamper_Interrupt_Callback = it_cb->Tamper_Interrupt_Callback;

	if ((int)it_cb->Alarm_A_Interrupt_Callback | (int)it_cb->Alarm_B_Interrupt_Callback)
	{
		WHT_EXTI_Config.Line = Exti_Line_RTC_Alarm;
		WHT_EXTI_Config.Interrupt_Callback = RTC_BSP_Alarm_IT_CB;
		if (WHT_EXTI_BSP.WHT_Register(&WHT_EXTI_Config) == SUCCESS)
		{
			WHT_EXTI_BSP.WHT_Config(&WHT_EXTI_Config);
			RTC_AlarmCmd(RTC_Alarm_A, it_cb->Alarm_A_Interrupt_Callback == NULL ? DISABLE : ENABLE);
			RTC_AlarmCmd(RTC_Alarm_B, it_cb->Alarm_B_Interrupt_Callback == NULL ? DISABLE : ENABLE);
		}
	}
	if (it_cb->Wakeup_Interrupt_Callback != NULL)
	{
		WHT_EXTI_Config.Line = Exti_Line_RTC_Wakeup;
		WHT_EXTI_Config.Interrupt_Callback = RTC_BSP_Wakeup_IT_CB;
		if (WHT_EXTI_BSP.WHT_Register(&WHT_EXTI_Config) == SUCCESS)
		{
			WHT_EXTI_BSP.WHT_Config(&WHT_EXTI_Config);
			RTC_ITConfig(RTC_IT_WUT, ENABLE);
			RTC_WakeUpCmd(ENABLE);
		}
	}
	if ((int)it_cb->Time_Stamp_Interrupt_Callback | (int)it_cb->Tamper_Interrupt_Callback)
	{
		WHT_EXTI_Config.Line = Exti_Line_RTC_Time;
		WHT_EXTI_Config.Interrupt_Callback = RTC_BSP_TAMP_STAMP_IT_CB;
		if (WHT_EXTI_BSP.WHT_Register(&WHT_EXTI_Config) == SUCCESS)
		{
			WHT_EXTI_BSP.WHT_Config(&WHT_EXTI_Config);
			RTC_ITConfig(RTC_IT_TS | RTC_IT_TAMP, ENABLE);
			RTC_TimeStampCmd(RTC_TimeStampEdge_Rising, it_cb->Time_Stamp_Interrupt_Callback == NULL ? DISABLE : ENABLE);
			RTC_TamperCmd(RTC_Tamper_1, it_cb->Tamper_Interrupt_Callback == NULL ? DISABLE : ENABLE);
			RTC_TamperCmd(RTC_Tamper_2, it_cb->Tamper_Interrupt_Callback == NULL ? DISABLE : ENABLE);
		}
	}
}
/*RTC获取运行状态*/
static WHT_RTC_State_enum WHT_RTC_BSP_Get_State(WHT_RTC_Clk_enum clk_source, const WHT_RTC_IT_CB_t* it_cb)
{
#define RTCEN_Bit           (0x01<<15)
	unsigned int RCC_BDCR_Value;

	/**********通过BDCR寄存器的RTC时钟使能/RTC时钟源判断是否上次配置过*************/
	RCC_BDCR_Value = RCC->BDCR;
	if ((RCC_BDCR_Value & RTCEN_Bit) == RESET)                    //RTC En bit
		return RTC_Running_Stop;
	if ((RCC_BDCR_Value & (clk_source & 0x00000300)) != (clk_source & 0x00000300))//RTC clock source
		return RTC_Running_Stop;

	/*******是否内部时钟提供RTC********/
	if (clk_source == LSI_RC_40000Hz)
	{
		RCC_LSICmd(ENABLE);
		while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
		{
		}
	}
	else if (clk_source == LSE_OSC_32768Hz)
	{
		RCC_LSEConfig(RCC_LSE_ON);
		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
		{
		}
	}
	else if (clk_source == HSE_OSC_Div32)
	{
		RCC_HSEConfig(RCC_HSE_ON);
		while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET)
		{
		}
	}
	RTC_WaitForSynchro();//等待RTC寄存器时钟同步

	WHT_RTC_BSP_Register_IT_CB(it_cb);

	return RTC_Running_Well;
}
/*RTC配置*/
static void WHT_RTC_BSP_Config(WHT_RTC_Clk_enum clk_source, const WHT_RTC_IT_CB_t* it_cb)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//open PWR BKP clock
	RCC_BackupResetCmd(ENABLE);                        //reset all BKP registers data 会将备份数据也给复位的
	RCC_BackupResetCmd(DISABLE);

	PWR_BackupAccessCmd(ENABLE);                       //使能RTC和备份寄存器和备份SRAM的写操作
	if (clk_source == LSI_RC_40000Hz)
	{
		RCC_LSICmd(ENABLE);
		while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
		{
		}
	}
	else if (clk_source == LSE_OSC_32768Hz)
	{
		int count_over = 72000000;//for 72MHZ wait > 1sec

		RCC_LSEConfig(RCC_LSE_ON);
		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
		{
			if(count_over-- == 0)
			{
				WHT_RTC_BSP_Config(LSI_RC_40000Hz, it_cb);//防止外部无晶振或晶振异常
				return;
			}
		}
	}
	else if (clk_source == HSE_OSC_Div32)
	{
		RCC_HSEConfig(RCC_HSE_ON);
		while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET)
		{
		}
	}
	else
		return;
	RCC_RTCCLKConfig(clk_source);//RTC clock source select
	RCC_RTCCLKCmd(ENABLE);
	RTC_WaitForSynchro();                  //等待RTC寄存器时钟同步
	/*初始化同步 / 异步预分频器的值*/
	RTC_InitTypeDef RTC_InitStruct;

	//default 1Hz
	if (clk_source == LSI_RC_40000Hz)
	{
		/*设置异步预分频器的值*/
		RTC_InitStruct.RTC_AsynchPrediv = 40000 / 256 - 1;
		/*设置同步预分频器的值*/
		RTC_InitStruct.RTC_SynchPrediv = 256 - 1;
	}
	else if (clk_source == LSE_OSC_32768Hz)
	{
		/*设置异步预分频器的值*/
		RTC_InitStruct.RTC_AsynchPrediv = 32768 / 256 - 1;
		/*设置同步预分频器的值*/
		RTC_InitStruct.RTC_SynchPrediv = 256 - 1;
	}
	else if (clk_source == HSE_OSC_Div32)
	{
		/*设置异步预分频器的值*/
		RTC_InitStruct.RTC_AsynchPrediv = 4000000 / 32 / 500 - 1;
		/*设置同步预分频器的值*/
		RTC_InitStruct.RTC_SynchPrediv = 500 - 1;
	}
	RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
	RTC_Init(&RTC_InitStruct);
	PWR_BackupAccessCmd(DISABLE);//关闭RTC和备份寄存器和备份SRAM的写操作

	WHT_RTC_BSP_Register_IT_CB(it_cb);
}

/*RTC获取时钟源*/
static WHT_RTC_Clk_enum WHT_RTC_BSP_Get_Clock_Source(void)
{
	unsigned int RCC_BDCR_Value;

	RCC_BDCR_Value = RCC->BDCR & 0x00000300;
	if (RCC_BDCR_Value == LSE_OSC_32768Hz)
		return LSE_OSC_32768Hz;
	else if (RCC_BDCR_Value == LSI_RC_40000Hz)
		return LSI_RC_40000Hz;
	else if (RCC_BDCR_Value == (HSE_OSC_Div32 & 0x00000300))
		return HSE_OSC_Div32;
	else
		return NO_Clk;
}
/*RTC设置时间日期*/
static void WHT_RTC_BSP_Set_Time_Date(const WHT_RTC_Calendar_t* calendar)
{
	RTC_TimeTypeDef RTC_TimeStruct;
	RTC_DateTypeDef RTC_DateStruct;

	/*时间*/
	RTC_TimeStruct.RTC_H12 = RTC_H12_AM;
	RTC_TimeStruct.RTC_Hours = calendar->Hour;
	RTC_TimeStruct.RTC_Minutes = calendar->Min;
	RTC_TimeStruct.RTC_Seconds = calendar->Sec;
	RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
	/*日期*/
	RTC_DateStruct.RTC_WeekDay = calendar->Wday;
	RTC_DateStruct.RTC_Date = calendar->Mday;
	RTC_DateStruct.RTC_Month = calendar->Month;
	RTC_DateStruct.RTC_Year = calendar->Year - 2000;
	RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
}
/*RTC获取时间日期*/
static void WHT_RTC_BSP_Get_Time_Date(WHT_RTC_Calendar_t* calendar)
{
	static RTC_TimeTypeDef RTC_TimeStruct;
	static RTC_DateTypeDef RTC_DateStruct;

	/*时间 日期*/
	RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
	RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
	calendar->Hour = RTC_TimeStruct.RTC_Hours;
	calendar->Min = RTC_TimeStruct.RTC_Minutes;
	calendar->Sec = RTC_TimeStruct.RTC_Seconds;

	calendar->Wday = RTC_DateStruct.RTC_WeekDay;
	calendar->Mday = RTC_DateStruct.RTC_Date;
	calendar->Month = RTC_DateStruct.RTC_Month;
	calendar->Year = RTC_DateStruct.RTC_Year + 2000;
}
/*RTC设置闹钟A*/
static void WHT_RTC_BSP_Set_Alarm_A(const WHT_RTC_Calendar_t* alarm)
{
	RTC_AlarmTypeDef RTC_AlarmStruct;

	/* 失能闹钟 ，在设置闹钟时间的时候必须先失能闹钟 */
	RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
	/* 清除闹钟中断标志位 */
	RTC_ClearFlag(RTC_FLAG_ALRAF);
	/* 设置闹钟时间 */
	RTC_AlarmStruct.RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
	RTC_AlarmStruct.RTC_AlarmTime.RTC_Hours = alarm->Hour;
	RTC_AlarmStruct.RTC_AlarmTime.RTC_Minutes = alarm->Min;
	RTC_AlarmStruct.RTC_AlarmTime.RTC_Seconds = alarm->Sec;
	RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;//屏蔽日期和星期
	RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;//日期模式或星期模式
	RTC_AlarmStruct.RTC_AlarmDateWeekDay = RTC_Weekday_Monday;
	RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStruct);
	RTC_ITConfig(RTC_IT_ALRA, ENABLE);
	RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
}
/*RTC设置闹钟B*/
static void WHT_RTC_BSP_Set_Alarm_B(const WHT_RTC_Calendar_t* alarm)
{
	RTC_AlarmTypeDef RTC_AlarmStruct;

	/* 失能闹钟 ，在设置闹钟时间的时候必须先失能闹钟 */
	RTC_AlarmCmd(RTC_Alarm_B, DISABLE);
	/* 清除闹钟中断标志位 */
	RTC_ClearFlag(RTC_FLAG_ALRBF);
	/* 设置闹钟时间 */
	RTC_AlarmStruct.RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
	RTC_AlarmStruct.RTC_AlarmTime.RTC_Hours = alarm->Hour;
	RTC_AlarmStruct.RTC_AlarmTime.RTC_Minutes = alarm->Min;
	RTC_AlarmStruct.RTC_AlarmTime.RTC_Seconds = alarm->Sec;
	RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;//屏蔽日期和星期
	RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;//日期模式或星期模式
	RTC_AlarmStruct.RTC_AlarmDateWeekDay = RTC_Weekday_Monday;
	RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_B, &RTC_AlarmStruct);
	RTC_ITConfig(RTC_IT_ALRB, ENABLE);
	RTC_AlarmCmd(RTC_Alarm_B, ENABLE);
}

/*全局常量*/
const WHT_RTC_BSP_t WHT_RTC_BSP =
{
	.WHT_Set_Time = WHT_RTC_BSP_Set_Time_Date,
	.WHT_Get_Time = WHT_RTC_BSP_Get_Time_Date,
	.WHT_Get_State = WHT_RTC_BSP_Get_State,
	.WHT_Get_Clock_Source = WHT_RTC_BSP_Get_Clock_Source,
	.WHT_Set_Clock_Source = WHT_RTC_BSP_Config,
	.WHT_Set_Alarm_A = WHT_RTC_BSP_Set_Alarm_A,
	.WHT_Set_Alarm_B = WHT_RTC_BSP_Set_Alarm_B,
};
